﻿using System;
using System.Globalization;
using System.Xml.Linq;

using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

using SeriesManager.Enum;
using SeriesManager.Model.Banner;

namespace SeriesManager.Model
{
    public sealed class EpisodeModel : BindableBase
    {
        #region Properties

        private readonly int id;
        private readonly SeasonModel season;
        private string imdbID;
        private int ratingCount;
        private int absoluteNumber;
        private DateTime lastUpdated;
        private int seasonNumber;
        private int number;
        private string name;
        private DateTime firstAired;
        private string[] director;
        private string[] guestStars;
        private string overview;
        private double rating = 0.1;
        private string[] writer;
        private BannerBaseModel image;
        private WatchState state = WatchState.Unwatched;

        public int ID
        {
            get
            {
                return this.id;
            }
        }

        public SeasonModel Season
        {
            get
            {
                return this.season;
            }
        }

        public string ImdbID
        {
            get
            {
                return this.imdbID;
            }
            set
            {
                base.SetProperty(ref this.imdbID, value);
            }
        }

        public int RatingCount
        {
            get
            {
                return this.ratingCount;
            }
            set
            {
                base.SetProperty(ref this.ratingCount, value);
            }
        }

        public int AbsoluteNumber
        {
            get
            {
                return this.absoluteNumber;
            }
            set
            {
                base.SetProperty(ref this.absoluteNumber, value);
            }
        }

        public DateTime LastUpdated
        {
            get
            {
                return this.lastUpdated;
            }
            set
            {
                base.SetProperty(ref this.lastUpdated, value);
            }
        }

        public int SeasonNumber
        {
            get
            {
                return this.seasonNumber;
            }
            set
            {
                base.SetProperty(ref this.seasonNumber, value);
            }
        }
      
        public int Number
        {
            get 
            { 
                return this.number; 
            }
            set 
            { 
                SetProperty(ref this.number, value); 
            }
        }

        public string Name
        { 
            get 
            { 
                return name; 
            }
            set 
            { 
                base.SetProperty(ref this.name, value); 
            }
        }

        public DateTime FirstAired
        {
            get 
            { 
                return firstAired; 
            }
            set 
            {
                base.SetProperty(ref this.firstAired, value);
            }
        }

        public string[] Director
        {
            get 
            { 
                return director; 
            }
            set 
            { 
                base.SetProperty(ref this.director, value); 
            }
        }

        public string[] GuestStars
        {
            get 
            { 
                return guestStars; 
            }
            set 
            { 
                base.SetProperty(ref this.guestStars, value); 
            }
        }

        public string Overview
        {
            get 
            { 
                return overview; 
            }
            set 
            { 
                base.SetProperty(ref this.overview, value); 
            }
        }

        public double Rating
        {
            get 
            { 
                return rating; 
            }
            set 
            { 
                base.SetProperty(ref this.rating, value); 
            }
        }

        public string[] Writer
        {
            get 
            { 
                return writer; 
            }
            set 
            { 
                base.SetProperty(ref this.writer, value); 
            }
        }

        public BannerBaseModel Image
        {
            get 
            { 
                return this.image; 
            }
            set 
            {
                base.SetProperty(ref this.image, value); 
            }
        }

        public WatchState State
        {
            get
            {
                return this.state;
            }
            set
            {
                WatchState oldState = this.state;
                if (oldState != WatchState.UnAired && base.SetProperty(ref this.state, value))
                {
                    EpisodeModel_StateChanged(oldState);
                }
            }
        }

        #endregion
        
        public EpisodeModel(int episodeID, SeasonModel season, DateTime firstAired)
        {
            this.id = episodeID;
            this.season = season;
            this.firstAired = firstAired;

            if (firstAired.Date.CompareTo(DateTime.Today) > 0 || firstAired.CompareTo(DateTime.MinValue) == 0)
            {
                this.State = WatchState.UnAired;
            }
            AddEpisodeState();
        }

        private void EpisodeModel_StateChanged(WatchState oldState)
        {
            switch (oldState)
            {
                case WatchState.Watched:
                    this.Season.Watched.Remove(this);
                    this.Season.Series.Watched.Remove(this);
                    break;
                case WatchState.Unwatched:
                    this.Season.Unwatched.Remove(this);
                    this.Season.Series.Unwatched.Remove(this);
                    break;
                case WatchState.UnAired:
                    this.Season.UnAired.Remove(this);
                    this.Season.Series.UnAired.Remove(this);
                    break;
            }

            AddEpisodeState();
        }

        private void AddEpisodeState()
        {
            switch (this.State)
            {
                case WatchState.Watched:
                    this.Season.Watched.Add(this);
                    this.Season.Series.Watched.Add(this);
                    break;
                case WatchState.Unwatched:
                    this.Season.Unwatched.Add(this);
                    this.Season.Series.Unwatched.Add(this);
                    break;
                case WatchState.UnAired:
                    this.Season.UnAired.Add(this);
                    this.Season.Series.UnAired.Add(this);
                    break;
            }
        }
    }
}
